In general, a processor system typically includes a main memory and a processor. The processor system may also include a cache memory to serve as a buffer memory between the main memory and the processor. The cache memory includes a data cache and an instruction cache directly accessible by the processor. The data cache is a portion of the cache memory that stores data accessible by instructions of a program executable by the processor, and the instruction cache is another portion of the cache memory that stores those instructions.
A protocol known as cache coherence is typically used to manage the data cache so that all cores and/or processors within a coherence domain (e.g., a processor having multiple cores or a processor system having multiple processors) may access the same value of a particular memory address. Data caches are maintained to be coherent both within a processor and/or across all processors in a multiple-processor system. A cache coherence protocol ensures that changes in the value of shared data on, for example, one processor are available and/or accessible throughout the entire processor system. In particular, cache coherence may be maintained by propagating the latest value or by invalidating incoherent copies of an old value (or all copies of the old value) in data caches.
In some processor systems, code may be dynamically generated using load and store instructions (i.e., new code) during a code generation process. For example, the code generation process may include a dynamic optimizer, an interpreter, and/or a just-in-time (JIT) compiler associated with a managed runtime environment (MRTE) for translating and/or converting bytecode (e.g., computer object code associated with a program written in a particular source code such as C or C++) into platform-specific executable code for an underlying processor to execute (e.g., native machine language instructions). However, without explicit direction, instruction caches may not be coherent between processors or within the same processor and/or processor system. As a result, the new code may not be propagated throughout the instruction caches and, thus, may not be observed by some cores and/or processors, including the generating processor, before cache coherence is enforced.
To increase performance, processor systems implemented using, for example, the Intel® Itanium® technology may not guarantee that instruction caches are coherent without explicit software control. In processor systems based on the Intel® Itanium® technology, a flush-cache instruction (e.g., fc) may be used to enforce instruction-cache coherence. In particular, the flush-cache instruction may flush data associated with a particular memory address from all caches associated with a core and/or a processor. The particular code sequence (e.g., the flush-cache instruction) required to ensure coherence is architecturally-specified and dependent on the nature of the code changes and the sharing of instructions across multiple cores and/or processors in a processor system. Different code sequences are necessary because of the different coherence requirements within a core/processor and/or between cores/processors. For example, a set of code sequences may be associated with self-modifying code (SMC) to ensure coherence within a core while another set of code sequences may be associated with cross-modifying code (CMC) to ensure coherence across all cores in a processor system. For processors implemented using the Intel® Itanium® technology, additional information pertinent to the code sequences is available in the Itanium® Software Developer's Manual, vol. 2 (October 2002) developed by Intel® Corporation. Processors implemented using other processing technology may have other requirements to ensure coherence. Further, the noted code sequences are typically executed to perform a cache flush during the code generation process. Thus, the code sequences require coordination between the different processors involved and create undesirable latency to enforce instruction-cache coherence.